package com.ltv.xiangqibook.web;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.datastore.Query.FilterOperator;

/**
 * This is the utility class for all servlets. It provides method for inserting,
 * deleting, searching the entity from data store.
 * 
 */
public class Util {

	private static final Logger logger = Logger.getLogger(Util.class.getCanonicalName());
	private static DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

	/**
	 * Add the entity to the datastore
	 * @param entity
	 *          : entity to be persisted
	 */
	public static void persistEntity(Entity entity) {
		logger.log(Level.INFO, "Saving entity");
		Transaction txn = datastore.beginTransaction();
		try {
			datastore.put(entity);
			txn.commit();
		} finally {
			if (txn.isActive()) {
				txn.rollback();
			}
		}
	}

	/**
	 * Delete the entity from persistent store represented by the key
	 * 
	 * @param key
	 *          : key to delete the entity from the persistent store
	 */
	public static void deleteEntity(Key key) {
		logger.log(Level.INFO, "Deleting entity");
		Transaction txn = datastore.beginTransaction();
		try {
			datastore.delete(key);
			txn.commit();
		} finally {
			if (txn.isActive()) {
				txn.rollback();
			}
		}
	}

	/**
	 * Delete the entities represented by a list of keys
	 * 
	 * @param keys : keys for the entities that are to be deleted
	 */
	public static void deleteEntity(final List<Key> keys) {
		datastore.delete(new Iterable<Key>() {
			public Iterator<Key> iterator() {
				return keys.iterator();
			}
		});
	}

	/**
	 * Search and return the entity from the datastore . If absent , return null
	 * 
	 * @param key
	 *          : key to find the entity
	 * @return entity
	 */
	public static Entity findEntity(Key key) {
		logger.log(Level.INFO, "Search the entity");
		try {
			return datastore.get(key);
		} catch (EntityNotFoundException e) {
			return null;
		}
	}

	/***
	 * Search entities based on search criteria
	 * 
	 * @param kind
	 * @param searchBy
	 *          : Searching Criteria (Property)
	 * @param searchFor
	 *          : Searching Value (Property Value)
	 * @return List all entities of a kind from the cache or datastore (if not in
	 *         cache) with the specified properties
	 */
	@SuppressWarnings("deprecation")
	public static Iterable<Entity> listEntities(String kind, String searchBy, String searchFor) {
		logger.log(Level.INFO, "Search entities based on search criteria");
		Query query = new Query(kind);
		if (searchFor != null && !"".equals(searchFor)) {
			query.addFilter(searchBy, FilterOperator.EQUAL, searchFor);
		}
		PreparedQuery pq = datastore.prepare(query);
		return pq.asIterable();
	}


	/**
	 * Utility method to send the error back to UI
	 * 
	 * @throws IOException
	 */
	public static String getErrorResponse(Exception ex) throws IOException {
		return "Error:" + ex.toString();
	}

	/**
	 * Utility method to get the datastore service in entities
	 * 
	 * @return datastore
	 */
	public static DatastoreService getDatastoreServiceInstance() {
		return datastore;
	}
}